home *** CD-ROM | disk | FTP | other *** search
/ CICA 1993 April / CICA MS Windows - April 1993.iso / unzipped / programr / textview / demo / main.c < prev    next >
C/C++ Source or Header  |  1991-06-13  |  14KB  |  531 lines

  1. /*****************************************************************************
  2.  
  3.     main.c
  4.     ------
  5.  
  6.     This is the entry module for the TextView demonstration application. The
  7.     program shows you how you can use TextView to add a real-time tracing
  8.     facility to an application, so that you can write debug messages to
  9.     the screen as easily as you could using printf() in a DOS application.
  10.  
  11.     The program sets up a main window that contains a 'Trace' menu. Items in
  12.     this menu enable you to turn the tracing facility on and off, and to
  13.     simulate your application writing messages to the trace window and
  14.     manipulating it.
  15.  
  16.     This source is Copyright (c) Alan Phillips 1991. It may be freely used
  17.     and adapted for non-commercial applications. Commercial and ShareWare
  18.     authors should first obtain the written permission of the author.
  19.  
  20.     The source is edited with a tab size of 4.
  21.  
  22. *****************************************************************************/
  23.  
  24. #define        MAINDEF
  25. #include    "stdhead.h"
  26. #include    "ident.h"
  27.  
  28. /*****************************************************************************
  29.  
  30.     Local Procedures
  31.     ----------------
  32.  
  33. *****************************************************************************/
  34.  
  35. static    BOOL    process_command(HWND,unsigned,WORD,LONG);
  36.  
  37.  
  38. /*****************************************************************************
  39.  
  40.     WinMain
  41.     -------
  42.  
  43.     This is the entry point from Windows
  44.  
  45.     reply = WinMain(hInstance,hPrevInstance,lpCmdLine,nCmdShow)
  46.  
  47.     int        reply;                    Reply to Windows
  48.     HANDLE    hInstance;                Handle of this instance
  49.     HANDLE    hPrevInstance;            Handle of previous instance
  50.     LPSTR    lpCmdLine;                Ptr to command line
  51.     int        nCmdShow;                ShowWindow() param
  52.  
  53. *****************************************************************************/
  54.  
  55. int        PASCAL    WinMain(HANDLE hInstance,HANDLE hPrevInstance,
  56.                         LPSTR lpCmdLine, int nCmdShow)
  57.  
  58. {
  59.     WNDCLASS    wc;                    /* window class struct */
  60.     MSG            msg;                /* message from Windows */
  61.     
  62.     /* Save our instance handle in global data */
  63.  
  64.     hInst    = hInstance;
  65.  
  66.     /* Set up a window class for the main window. Since the window is not
  67.     *  going to be used for anything in this demonstration, we don't need
  68.     *  to set up anything special
  69.     */
  70.  
  71.     if ( hPrevInstance == NULL )
  72.     {
  73.         /* Set up class struct for the main window */
  74.  
  75.         wc.style            = CS_HREDRAW | CS_VREDRAW;
  76.         wc.lpfnWndProc        = WndProc;
  77.         wc.cbClsExtra        = 0;
  78.         wc.cbWndExtra        = 0;
  79.         wc.hInstance        = hInstance;
  80.         wc.hIcon            = LoadIcon(hInstance,"MAIN_ICON");
  81.         wc.hCursor            = LoadCursor(NULL,IDC_ARROW);
  82.         wc.hbrBackground    = GetStockObject(WHITE_BRUSH);
  83.         wc.lpszMenuName        = "MAIN_MENU";
  84.         wc.lpszClassName    = "TR_Window";
  85.  
  86.         /* And register it */
  87.  
  88.         RegisterClass(&wc);
  89.  
  90.     }
  91.  
  92.     /* Create the main window. We make it fairly small as it doesn't have
  93.     *  to do anything
  94.     */
  95.  
  96.     hMainWnd    = CreateWindow(    "TR_Window",
  97.                                 "TextView DLL Demo",
  98.                                 WS_OVERLAPPEDWINDOW,
  99.                                 CW_USEDEFAULT,
  100.                                 CW_USEDEFAULT,
  101.                                 300,
  102.                                 150,
  103.                                 NULL,
  104.                                 NULL,
  105.                                 hInstance,
  106.                                 NULL );
  107.  
  108.     if ( hMainWnd == NULL )
  109.         return(FALSE);
  110.  
  111.     /* Make the main window visible and update the client area */
  112.  
  113.     ShowWindow(hMainWnd,nCmdShow);
  114.     UpdateWindow(hMainWnd);
  115.  
  116.     /* In order to create TextView windows, you need to call a TextView
  117.     *  routine to register one or more window classes. The information passed
  118.     *  is a subset of the information you set up for a call to RegisterClass;
  119.     *  most of the details are supplied by TextView itself. Here you can
  120.     *  specify an icon handle, and the background brush.
  121.     *
  122.     *  Note that this routine is not in the TextView DLL itself, but is
  123.     *  in the import library TEXTVIEW.LIB
  124.     */
  125.  
  126.     TVRegisterClass(hInstance,"TRACE_WINDOW",LoadIcon(hInstance,"MAIN_ICON"),
  127.                             GetStockObject(WHITE_BRUSH));
  128.  
  129.     /* And now we can enter the message loop and wait for the user to do
  130.     *  something
  131.     */
  132.  
  133.     while ( GetMessage(&msg,NULL,0,0) )
  134.     {
  135.         TranslateMessage(&msg);
  136.         DispatchMessage(&msg);
  137.     }
  138.  
  139.     /* And when we get here, that's it */
  140.  
  141.     return( msg.wParam );
  142.  
  143. }
  144.  
  145.  
  146.  
  147. /*****************************************************************************
  148.  
  149.     WndProc
  150.     -------
  151.  
  152.     This is the Windows function to receive messages for the main window
  153.  
  154.     reply = WndProc(hWnd,iMessage,wParam,lParam)
  155.  
  156.     long        reply;                Reply to Windows
  157.     HWND        hWnd;                Handle to window
  158.     unsigned    iMessage;            Message id
  159.     WORD        wParam;                Message parameter
  160.     LONG        lParam;                Message parameter
  161.  
  162. *****************************************************************************/
  163.  
  164. long    FAR    PASCAL    Wndproc(HWND hWnd, unsigned iMessage,WORD wParam,
  165.                             LONG lParam)
  166.  
  167. {
  168.     /* Switch on the message type */
  169.     
  170.     switch ( iMessage )
  171.     {
  172.                     
  173.         case WM_DESTROY:                        /* window has gone */
  174.  
  175.                     PostQuitMessage(0);
  176.                     return(0);
  177.                     
  178.         case WM_COMMAND:                        /* command */
  179.  
  180.                     /* Pass the command down to a separate routine to avoid
  181.                     *  this switch getting horrendously large
  182.                     */
  183.                             
  184.                     if ( process_command(hWnd,iMessage,wParam,lParam) )
  185.                         break;
  186.                     else
  187.                         return(0);
  188.  
  189.         default:                                /* anything else */
  190.         
  191.                     break;
  192.     }
  193.  
  194.     return( DefWindowProc(hWnd,iMessage,wParam,lParam) );
  195.  
  196. }
  197.  
  198.  
  199. /*****************************************************************************
  200.  
  201.     process_command
  202.     ---------------
  203.  
  204.     Processes one command from a WM_COMMAND message to the main window. This
  205.     is done in a separate routine to keep the main message loop switch a
  206.     reasonable size
  207.  
  208.     reply    = process_command(hWnd,iMessage,wParam,lParam)
  209.  
  210.     BOOL    reply;                TRUE if message handled here
  211.     HWND    hWnd;                Handle to window
  212.     unsigned    iMessage;        Message id
  213.     WORD    wParam;                Message parameter
  214.     LONG    lParam;                Message parameter
  215.  
  216. *****************************************************************************/
  217.  
  218. static    BOOL    process_command(HWND hWnd,unsigned iMessage,WORD wParam,
  219.                                 LONG lParam)
  220.  
  221. {
  222.     static    int        trace_count = 1;        /* test trace counts */
  223.  
  224.     int        i;                                /* work variable */
  225.     FARPROC    lpAbout;                        /* about dialog proc instance */
  226.     HMENU    hMenu;                            /* handle to main window menu */
  227.  
  228.     /* Switch on the WM_COMMAND parameter */
  229.     
  230.     switch ( wParam )
  231.     {
  232.                         
  233.         case IDM_HELP_ABOUT:                /* About... */
  234.  
  235.                         /* Run the "about" dialog */
  236.  
  237.                         lpAbout    = MakeProcInstance(AboutDlgProc,hInst);
  238.                         DialogBox(    hInst,
  239.                                     "ABOUT_DLG",
  240.                                     hWnd,
  241.                                     lpAbout);
  242.                         FreeProcInstance(lpAbout);
  243.                         break;
  244.  
  245.         case IDM_TRACE_ON:                    /* Trace start */
  246.  
  247.                         /* Start tracing, creating a trace window if we
  248.                         *  don't already have one
  249.                         */
  250.  
  251.                         start_tracing(hWnd);
  252.                         break;
  253.  
  254.         case IDM_TRACE_OFF:                    /* Trace stop */
  255.  
  256.                         /* Here we just set our 'tracing' flag to FALSE, so
  257.                         *  that the trace() routine does nothing. We leave the
  258.                         *  trace window open, and adjust items in our menu
  259.                         */
  260.  
  261.                         tracing    = FALSE;
  262.                         EnableMenuItem(GetMenu(hWnd),IDM_TRACE_OFF,
  263.                                     MF_GRAYED | MF_BYCOMMAND);
  264.                         EnableMenuItem(GetMenu(hWnd),IDM_TRACE_ON,
  265.                                     MF_ENABLED | MF_BYCOMMAND);
  266.                         break;
  267.  
  268.         case IDM_TRACE_KILLWND:                /* Trace kill window */
  269.  
  270.                         /* Here we actually destroy the trace window and lose
  271.                         *  all its contents
  272.                         */
  273.                         
  274.                         kill_trace_window(hWnd);
  275.  
  276.                         /* Reset our private message counter to the start again */
  277.                         
  278.                         trace_count    = 1;
  279.                         break;
  280.  
  281.         case IDM_TRACE_TEST:                /* Trace write message */
  282.  
  283.                         /* Call the trace routine to write one line to
  284.                         *  the trace window. Note that this menu option is
  285.                         *  always enabled, to demonstrate how lines are
  286.                         *  ignored if tracing is not active
  287.                         */
  288.  
  289.                         trace("Test message %d",RGB(0,128,128),
  290.                                         trace_count);   
  291.                         trace_count++;
  292.                         break;
  293.  
  294.         case IDM_TRACE_MTEST:                /* trace write batch */
  295.  
  296.                         /* Call the trace routine to write a batch of lines to
  297.                         *  the trace window. Note that this menu option is
  298.                         *  always enabled, to demonstrate how lines are
  299.                         *  ignored if tracing is not active
  300.                         *
  301.                         *  For this option, the lines are written to the
  302.                         *  trace window as they are sent, so that the process
  303.                         *  is relatively slow
  304.                         *
  305.                         */
  306.  
  307.                         hourglass_on(hWnd);
  308.  
  309.                         for ( i = 1; i <= 200; i++ )
  310.                         {
  311.                             if ( !trace("Test message %d",RGB(128,0,128),trace_count) )
  312.                                 break;
  313.                                 
  314.                             trace_count++;
  315.                         }
  316.  
  317.                         hourglass_off();
  318.                         
  319.                         break;
  320.  
  321.         case IDM_TRACE_MTESTF:                /* trace write batch fast */
  322.  
  323.                         /* Call the trace routine to write a batch of lines to
  324.                         *  the trace window.
  325.                         *  
  326.                         *  For this option, we disable redrawing the trace
  327.                         *  window before we start, and enable it when we've
  328.                         *  done. This inhibits TextView from writing to the
  329.                         *  screen and scrolling the window, so the process
  330.                         *  is much faster that the option above.
  331.                         *
  332.                         *
  333.                         *  Note that since this option is always available,
  334.                         *  we need to check ourselves that the trace window
  335.                         *  exists.
  336.                         */
  337.  
  338.                         if ( hTraceWnd == NULL )
  339.                             break;
  340.  
  341.                         /* The window exists, so disable redrawing */
  342.  
  343.                         TVSetRedraw(hTraceWnd,FALSE);
  344.  
  345.                         /* And send a block of messages */
  346.  
  347.                         hourglass_on(hWnd);
  348.  
  349.                         for ( i = 1; i <= 200; i++ )
  350.                         {
  351.                             if ( !trace("Test message %d",RGB(0,255,0),trace_count) )
  352.                                 break;
  353.                                 
  354.                             trace_count++;
  355.                         }
  356.  
  357.                         /* Now re-enable redrawing, which will cause TextView
  358.                         *  to show the last screen-full of lines
  359.                         */
  360.  
  361.                         TVSetRedraw(hTraceWnd,TRUE);
  362.  
  363.                         hourglass_off();
  364.                         
  365.                         break;
  366.  
  367.         case IDM_TRACE_RESET:                /* trace reset */
  368.  
  369.                         /* Here we discard any contents in the trace window */
  370.                         
  371.                         reset_tracing(hWnd);
  372.  
  373.                         /* And reset our private message count */
  374.                         
  375.                         trace_count    = 1;
  376.                         break;
  377.  
  378.         case IDM_TRACE_SHOW:                /* trace show window */
  379.  
  380.                         /* Here we use the trace window handle to manipulate
  381.                         *  the window ourselves. There is no need to interact
  382.                         *  with the TextView DLL to do things like this
  383.                         */
  384.  
  385.                         if ( IsIconic(hTraceWnd) )
  386.                             ShowWindow(hTraceWnd,SW_SHOWNORMAL);
  387.                         else
  388.                             BringWindowToTop(hTraceWnd);
  389.                         break;
  390.  
  391.         case IDM_TRACE_STATUS:                /* trace status */
  392.  
  393.                         /* Tell the user the state of the trace window */
  394.                         
  395.                         report_trace_status();
  396.                         break;
  397.  
  398.         case IDM_TRACE_SCR_AUTO:            /* trace scroll auto */
  399.  
  400.                         /* Call the DLL to set the scroll state */
  401.  
  402.                         TVSetScrollState(hTraceWnd,TV_SCR_AUTO);
  403.  
  404.                         /* And adjust our menu to match */
  405.                         
  406.                         hMenu    = GetMenu(hMainWnd);
  407.  
  408.                         CheckMenuItem(hMenu,IDM_TRACE_SCR_AUTO,
  409.                                                     MF_CHECKED|MF_BYCOMMAND);
  410.                         CheckMenuItem(hMenu,IDM_TRACE_SCR_MAN,
  411.                                                     MF_UNCHECKED|MF_BYCOMMAND);
  412.                         break;
  413.  
  414.         case IDM_TRACE_SCR_MAN:                /* trace scroll manual */
  415.  
  416.                         /* Call the DLL to set the new state */
  417.  
  418.                         TVSetScrollState(hTraceWnd,TV_SCR_MANUAL);
  419.  
  420.                         /* And set our menu to match */
  421.                         
  422.                         hMenu    = GetMenu(hMainWnd);
  423.  
  424.                         CheckMenuItem(hMenu,IDM_TRACE_SCR_MAN,
  425.                                                     MF_CHECKED|MF_BYCOMMAND);
  426.                         CheckMenuItem(hMenu,IDM_TRACE_SCR_AUTO,
  427.                                                     MF_UNCHECKED|MF_BYCOMMAND);
  428.                         break;
  429.  
  430.         case IDM_TRACE_COPY:                /* trace copy trace window */
  431.  
  432.                         /* This takes a little time, so put up an hourglass
  433.                         *  cursor
  434.                         */
  435.                         
  436.                         hourglass_on(hWnd);
  437.  
  438.                         /* Do the copy */
  439.                         
  440.                         copy_trace_window(hWnd);
  441.  
  442.                         /* And restore the previous cursor */
  443.  
  444.                         hourglass_off();
  445.                         
  446.                         break;
  447.  
  448.         default:                            /* anything else */
  449.  
  450.                         /* Pass command to Windows */
  451.                         
  452.                         return(FALSE);
  453.     }
  454.  
  455.     /* If we get here, we processed the message, so tell caller not to pass
  456.     *  it to Windows
  457.     */
  458.  
  459.     return(TRUE);
  460.  
  461. }
  462.  
  463.  
  464. /*****************************************************************************
  465.  
  466.     AboutDlgProc
  467.     -------------
  468.  
  469.     This proc handles the "about" box dialog
  470.  
  471.     reply = AboutDlgProc(hDlg,message,wParam,lParam)
  472.  
  473.     BOOL    reply;                Reply to Windows
  474.     HWND    hDlg;                Handle to dialog box
  475.     unsigned    nMessage;        Message type
  476.     WORD    wParam;                Message parameter
  477.     LONG    lParam;                Message parameter
  478.  
  479. *****************************************************************************/
  480.  
  481. BOOL    FAR        PASCAL    AboutDlgProc(HWND hDlg,unsigned nMessage,
  482.                                           WORD wParam, LONG lParam)
  483.  
  484. {
  485.     char    buffer[32];                /* buffer for id strings */
  486.     int        mark,                    /* id numbers of sub-systems */
  487.             version,
  488.             cycle;
  489.     
  490.     /* Switch on the message type */
  491.     
  492.     switch ( nMessage )
  493.     {
  494.         case WM_INITDIALOG:
  495.         
  496.                         /* Write our id string to the text box */
  497.  
  498.                         wsprintf(buffer,"DemoProg %d.%02d.%03d",
  499.                                                 MARK, VERSION, CYCLE);
  500.                         SetDlgItemText(hDlg,ID_ABOUT_VN,buffer);
  501.  
  502.                         /* Then that of the TextView DLL */
  503.  
  504.                         TVVersion(&mark,&version,&cycle);
  505.                         wsprintf(buffer,"TextView DLL %d.%02d.%03d",
  506.                                                 mark,version,cycle);
  507.                         SetDlgItemText(hDlg,ID_TV_VERSION,buffer);
  508.                     
  509.                         break;
  510.  
  511.         case WM_COMMAND:
  512.  
  513.                         if ( wParam == ID_OK_BUTTON )
  514.                         {
  515.                             EndDialog(hDlg,TRUE);
  516.                             return(TRUE);
  517.                         }
  518.  
  519.                         break;
  520.  
  521.         default:
  522.  
  523.                         break;
  524.     }
  525.  
  526.     /* We didn't process the message here */
  527.  
  528.     return(FALSE);
  529.  
  530. }
  531.